package com.sunwayworld.basemodule.rm.equipment.equiptfileacq.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sunwayworld.baseline.framework.utils.FTPUtil;
import com.sunwayworld.baseline.framework.utils.SmbV1Utils;
import com.sunwayworld.baseline.framework.utils.SmbV23Utils;
import com.sunwayworld.basemodule.common.asynctask.bean.LimsAsynctaskBean;
import com.sunwayworld.basemodule.common.asynctask.config.AsyncTaskStatusEnum;
import com.sunwayworld.basemodule.common.asynctask.service.LimsAsynctaskService;
import com.sunwayworld.basemodule.rm.equipment.bean.LimsEquipmentBean;
import com.sunwayworld.basemodule.rm.equipment.equiptfileacq.bean.LimsEquiptFileAcqBean;
import com.sunwayworld.basemodule.rm.equipment.equiptfileacq.bean.LimsEquiptFileAcqConfigBean;
import com.sunwayworld.basemodule.rm.equipment.equiptfileacq.dao.LimsEquiptFileAcqConfigDao;
import com.sunwayworld.basemodule.rm.equipment.equiptfileacq.service.LimsEquiptFileAcqConfigService;
import com.sunwayworld.basemodule.rm.equipment.equiptfileacq.support.EquiptAcqEntity;
import com.sunwayworld.basemodule.rm.equipment.service.LimsEquipmentService;
import com.sunwayworld.framework.at.annotation.AuditTrailEntry;
import com.sunwayworld.framework.at.annotation.AuditTrailType;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.context.LocalContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.restful.data.RestJsonWrapperBean;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.module.mdm.user.bean.CoreUserBean;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Repository
@GikamBean
public class LimsEquiptFileAcqConfigServiceImpl implements LimsEquiptFileAcqConfigService {

    private static final Logger logger = LogManager.getLogger(LimsEquiptFileAcqConfigBean.class);

    @Autowired
    private LimsEquiptFileAcqConfigDao limsEquiptFileAcqConfigDao;

    @Autowired
    private LimsEquipmentService limsEquiptService;

    @Autowired
    @Lazy
    private LimsAsynctaskService asynctaskService;

    @Override
    @SuppressWarnings("unchecked")
    public LimsEquiptFileAcqConfigDao getDao() {
        return limsEquiptFileAcqConfigDao;
    }

    @Override
    @Transactional
    @AuditTrailEntry(AuditTrailType.INSERT)
    public Long insert(RestJsonWrapperBean jsonWrapper) {
        List<LimsEquiptFileAcqConfigBean> limsEquiptFileAcqConfigs = jsonWrapper.parse(LimsEquiptFileAcqConfigBean.class);
        List<Long> ids = ApplicationContextHelper.getNextIdentityList(limsEquiptFileAcqConfigs.size());
        limsEquiptFileAcqConfigs.forEach(e -> e.setId(ids.remove(0)));
        getDao().insert(limsEquiptFileAcqConfigs);
        return limsEquiptFileAcqConfigs.get(0).getId();
    }


    @Override
    public boolean connect(RestJsonWrapperBean wrapperBean) {
        LimsEquiptFileAcqConfigBean limsEquiptConfig = wrapperBean.parseUnique(LimsEquiptFileAcqConfigBean.class);
        String ip = limsEquiptConfig.getIp();
        int port = Integer.parseInt(limsEquiptConfig.getPort());
        String username = limsEquiptConfig.getUsername();
        String password = limsEquiptConfig.getPassword();
        String gainPath = limsEquiptConfig.getFilePath();

        String mode = limsEquiptConfig.getAcqMode();
        if (mode.equals("ftp")){
            boolean connectFlag = FTPUtil.connect(ip, port, username, password);
            if (!connectFlag){
                throw new InvalidDataException("连接失败");
            }
        }else if ("shareDocV23".equals(mode)){
            boolean connectFlag = SmbV23Utils.connect(ip, username, password);
            if (!connectFlag){
                throw new InvalidDataException("连接失败");
            }
        }else if ("shareDocV1".equals(mode)){
            boolean connectFlag = SmbV1Utils.connect(ip, username, password);
            if (!connectFlag){
                throw new InvalidDataException("连接失败");
            }
        }
        return true;
    }

    @Override
    public void acqFilesSchedule(RestJsonWrapperBean wrapper){
        List<LimsEquiptFileAcqConfigBean> limsEquiptFileAcqConfigBeanList = wrapper.parse(LimsEquiptFileAcqConfigBean.class);
        acqFilesSchedule(limsEquiptFileAcqConfigBeanList);
    }

    @Override
    public void acqFilesSchedule(String acqFrequency) {
        List<LimsEquiptFileAcqConfigBean> limsEquiptFileAcqConfigBeanList = selectListByFilter(SearchFilter.instance()
                .match("acqFrequency",acqFrequency).filter(MatchPattern.EQ));
        acqFilesSchedule(limsEquiptFileAcqConfigBeanList);
    }

    public void acqFilesSchedule(List<LimsEquiptFileAcqConfigBean> limsEquiptFileAcqConfigBeanList) {
        List<Long> equiptIds = limsEquiptFileAcqConfigBeanList.stream().map(e -> e.getEquiptId()).collect(Collectors.toList());
        List<LimsEquipmentBean> equiptBeans = limsEquiptService.selectListByIds(equiptIds);

        List<LimsAsynctaskBean> exists = asynctaskService.selectListByFilter(SearchFilter.instance()
                .match("executorname","equiptAcqFiles").filter(MatchPattern.EQ));
        List<String> goingStatusList = Arrays.asList(AsyncTaskStatusEnum.pendingAssign.status,AsyncTaskStatusEnum.hasAssign.status,AsyncTaskStatusEnum.executing.status);
        CoreUserBean loginUser = LocalContextHelper.getLoginUser();
        List<LimsAsynctaskBean> inserts = new ArrayList<>();
        for (LimsEquiptFileAcqConfigBean limsEquiptFileAcqConfigBean : limsEquiptFileAcqConfigBeanList){
            //存在进行中的，跳过
            boolean present = exists.stream().anyMatch(g -> limsEquiptFileAcqConfigBean.getId().equals(g.getTaskId()) &&
                    goingStatusList.contains(g.getExecStatus()));
            if(present){
                continue;
            }
            Optional<LimsEquipmentBean> equiptBeanOptional = equiptBeans.stream()
                    .filter(e -> e.getId().equals(limsEquiptFileAcqConfigBean.getEquiptId()))
                    .findFirst();
            if (!equiptBeanOptional.isPresent()) continue;

            LimsAsynctaskBean item = new LimsAsynctaskBean();
            item.setId(ApplicationContextHelper.getNextIdentity());
            item.setExecStatus(AsyncTaskStatusEnum.pendingAssign.status);
            item.setTaskId(limsEquiptFileAcqConfigBean.getId());
            item.setTaskName("设备文件采集");
            item.setExecutorName("equiptAcqFiles");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("equiptFileAcqConfig",limsEquiptFileAcqConfigBean);
            jsonObject.put("equiptCode",equiptBeanOptional.get().getEquipCode());
            item.setJsonParam(jsonObject.toJSONString());
            item.setServiceMethod("com.sunwayworld.basemodule.trm.equipt.equiptfileacq.service.LimsEquiptFileAcqConfigService.acqFilesWork");
            item.setTaskUserId(loginUser.getId());
            item.setTaskUserName(loginUser.getUserName());
            inserts.add(item);
        }
        asynctaskService.getDao().insert(inserts);
    }

    @Override
    public void acqFilesWork(JSONObject jsonParam) {
        String equiptCode = jsonParam.getString("equiptCode");
        LimsEquiptFileAcqConfigBean equiptFileAcqConfig = jsonParam.getObject("equiptFileAcqConfig",LimsEquiptFileAcqConfigBean.class);
        logger.info("设备文件->本地  开始  equiptCode:{}", equiptCode);

        EquiptAcqEntity equiptAcqEntity = new EquiptAcqEntity(equiptFileAcqConfig);
        //将文件从远程服务器抓取到本地
        List<LimsEquiptFileAcqBean> equiptFileAcqBeans = equiptAcqEntity.acqFiles();
        //解析文件
        equiptAcqEntity.analysisFiles(equiptFileAcqBeans);

        logger.info("设备文件->本地  结束  equiptCode:{} szie:{}", equiptCode);
    }
}
